<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    
    <title>Linux Signal Examples | jouyouyun&#39;s blog</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1">
    <meta name="description" content="信号是系统响应某些条件而产生的一个事件，接收到该信的进程做出相应的处理。通常信是由错误产生的，如段错误(SIGSEGV)。 但信还可以作为进程间通信的一种方式，由一个进程发送给另一个进程。
信号定义在 signal.h 文件中，以 SIG 作为开头，可用 kill -l 命令查看，详细信息参见 man 7 signal 。
信号处理
信号可以通过 signal 和 sigaction 函数来注册处理， signal 函数是 struct sigaction 中 sa_handler 的一种便捷实现。
signal 函数">
    <meta name="generator" content="Hugo 0.105.0">
    
    
    
    
      <meta name="robots" content="noindex, nofollow">
    

    
<link rel="stylesheet" href="/ananke/css/main.min.css" >



    
    
    
      

    

    
    
    <meta property="og:title" content="Linux Signal Examples" />
<meta property="og:description" content="信号是系统响应某些条件而产生的一个事件，接收到该信的进程做出相应的处理。通常信是由错误产生的，如段错误(SIGSEGV)。 但信还可以作为进程间通信的一种方式，由一个进程发送给另一个进程。
信号定义在 signal.h 文件中，以 SIG 作为开头，可用 kill -l 命令查看，详细信息参见 man 7 signal 。
信号处理
信号可以通过 signal 和 sigaction 函数来注册处理， signal 函数是 struct sigaction 中 sa_handler 的一种便捷实现。
signal 函数" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://jouyouyun.github.io/post/linux-signal-example/" /><meta property="article:section" content="post" />
<meta property="article:published_time" content="2018-11-13T21:38:21+08:00" />
<meta property="article:modified_time" content="2019-04-23T16:13:41+08:00" />

<meta itemprop="name" content="Linux Signal Examples">
<meta itemprop="description" content="信号是系统响应某些条件而产生的一个事件，接收到该信的进程做出相应的处理。通常信是由错误产生的，如段错误(SIGSEGV)。 但信还可以作为进程间通信的一种方式，由一个进程发送给另一个进程。
信号定义在 signal.h 文件中，以 SIG 作为开头，可用 kill -l 命令查看，详细信息参见 man 7 signal 。
信号处理
信号可以通过 signal 和 sigaction 函数来注册处理， signal 函数是 struct sigaction 中 sa_handler 的一种便捷实现。
signal 函数"><meta itemprop="datePublished" content="2018-11-13T21:38:21+08:00" />
<meta itemprop="dateModified" content="2019-04-23T16:13:41+08:00" />
<meta itemprop="wordCount" content="942">
<meta itemprop="keywords" content="signal,sigaction,alarm,kill,raise," /><meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Linux Signal Examples"/>
<meta name="twitter:description" content="信号是系统响应某些条件而产生的一个事件，接收到该信的进程做出相应的处理。通常信是由错误产生的，如段错误(SIGSEGV)。 但信还可以作为进程间通信的一种方式，由一个进程发送给另一个进程。
信号定义在 signal.h 文件中，以 SIG 作为开头，可用 kill -l 命令查看，详细信息参见 man 7 signal 。
信号处理
信号可以通过 signal 和 sigaction 函数来注册处理， signal 函数是 struct sigaction 中 sa_handler 的一种便捷实现。
signal 函数"/>

	
  </head>

  <body class="ma0 avenir bg-near-white">

    
   
  

  <header>
    <div class="bg-black">
      <nav class="pv3 ph3 ph4-ns" role="navigation">
  <div class="flex-l justify-between items-center center">
    <a href="/" class="f3 fw2 hover-white no-underline white-90 dib">
      
        jouyouyun&#39;s blog
      
    </a>
    <div class="flex-l items-center">
      

      
        <ul class="pl0 mr3">
          
          <li class="list f5 f4-ns fw4 dib pr3">
            <a class="hover-white no-underline white-90" href="/post/" title="Archives 页">
              Archives
            </a>
          </li>
          
          <li class="list f5 f4-ns fw4 dib pr3">
            <a class="hover-white no-underline white-90" href="/tags/" title="Tags 页">
              Tags
            </a>
          </li>
          
          <li class="list f5 f4-ns fw4 dib pr3">
            <a class="hover-white no-underline white-90" href="/categories/" title="Categories 页">
              Categories
            </a>
          </li>
          
        </ul>
      
      
<div class="ananke-socials">
  
    <a href="https://github.com/jouyouyun" target="_blank" class="github ananke-social-link link-transition stackoverflow link dib z-999 pt3 pt0-l mr1" title="GitHub link" rel="noopener" aria-label="follow on GitHub——Opens in a new window">
      
        <span class="icon"><svg style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512"  xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
  <path d="M256,32C132.3,32,32,134.8,32,261.7c0,101.5,64.2,187.5,153.2,217.9c11.2,2.1,15.3-5,15.3-11.1   c0-5.5-0.2-19.9-0.3-39.1c-62.3,13.9-75.5-30.8-75.5-30.8c-10.2-26.5-24.9-33.6-24.9-33.6c-20.3-14.3,1.5-14,1.5-14   c22.5,1.6,34.3,23.7,34.3,23.7c20,35.1,52.4,25,65.2,19.1c2-14.8,7.8-25,14.2-30.7c-49.7-5.8-102-25.5-102-113.5   c0-25.1,8.7-45.6,23-61.6c-2.3-5.8-10-29.2,2.2-60.8c0,0,18.8-6.2,61.6,23.5c17.9-5.1,37-7.6,56.1-7.7c19,0.1,38.2,2.6,56.1,7.7   c42.8-29.7,61.5-23.5,61.5-23.5c12.2,31.6,4.5,55,2.2,60.8c14.3,16.1,23,36.6,23,61.6c0,88.2-52.4,107.6-102.3,113.3   c8,7.1,15.2,21.1,15.2,42.5c0,30.7-0.3,55.5-0.3,63c0,6.1,4,13.3,15.4,11C415.9,449.1,480,363.1,480,261.7   C480,134.8,379.7,32,256,32z"/>
</svg>
</span>
      
<span class="new-window"><svg  height="8px"  style="enable-background:new 0 0 1000 1000;" version="1.1" viewBox="0 0 1000 1000"  xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<path d="M598 128h298v298h-86v-152l-418 418-60-60 418-418h-152v-86zM810 810v-298h86v298c0 46-40 86-86 86h-596c-48 0-86-40-86-86v-596c0-46 38-86 86-86h298v86h-298v596h596z" style="fill-rule:evenodd;clip-rule:evenodd;"/>
</svg>
</span></a>
  
</div>

    </div>
  </div>
</nav>

    </div>
  </header>



    <main class="pb7" role="main">
      
  
  <article class="flex-l flex-wrap justify-between mw8 center ph3">
    <header class="mt4 w-100">
      <aside class="instapaper_ignoref b helvetica tracked">
          
        POSTS
      </aside>
      










  <div id="sharing" class="mt3 ananke-socials">
    
  </div>


      <h1 class="f1 athelas mt3 mb1">Linux Signal Examples</h1>
      
      <p class="tracked">
         <strong>jouyouyun</strong>
      </p>
      
      
      
      <time class="f6 mv4 dib tracked" datetime="2018-11-13T21:38:21+08:00">十一月 13, 2018</time>
      

      
      
    </header>
    <div class="nested-copy-line-height lh-copy serif f4 nested-links mid-gray pr4-l w-two-thirds-l"><p>信号是系统响应某些条件而产生的一个事件，接收到该信的进程做出相应的处理。通常信是由错误产生的，如段错误(<code>SIGSEGV</code>)。 但信还可以作为进程间通信的一种方式，由一个进程发送给另一个进程。</p>
<p>信号定义在 <code>signal.h</code> 文件中，以 <code>SIG</code> 作为开头，可用 <code>kill -l</code> 命令查看，详细信息参见 <a href="http://man7.org/linux/man-pages/man7/signal.7.html">man 7 signal</a> 。</p>
<h2 id="信号处理">信号处理</h2>
<p>信号可以通过 <code>signal</code> 和 <code>sigaction</code> 函数来注册处理， <code>signal</code> 函数是 <code>struct sigaction</code> 中 <code>sa_handler</code> 的一种便捷实现。</p>
<h3 id="signal-函数"><code>signal</code> 函数</h3>
<p><strong>原型：</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> (<span style="color:#f92672">*</span>signal(<span style="color:#66d9ef">int</span> sig, <span style="color:#66d9ef">void</span> (<span style="color:#f92672">*</span>func)(<span style="color:#66d9ef">int</span>)))(<span style="color:#66d9ef">int</span>);
</span></span></code></pre></div><p>其中 <code>sig</code> 是需要捕获的 <code>signal number</code>, 后一个是捕获到信号后的处理函数指针，所以处理函数的原型必须是 <code>void func(int)</code> ，简单的代码示例如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;string.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;signal.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">handler</span>(<span style="color:#66d9ef">int</span> sig)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;Recieved signal: %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, sig);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">main</span>(<span style="color:#66d9ef">int</span> argc, <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>argv[])
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        signal(SIGINT, handler);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;Caught SIGINT, input &#39;quit&#39; to exit...</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// wait signal caught
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">char</span> buf[<span style="color:#ae81ff">1024</span>] <span style="color:#f92672">=</span> {<span style="color:#ae81ff">0</span>};
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">while</span> (<span style="color:#ae81ff">1</span>) {
</span></span><span style="display:flex;"><span>                printf(<span style="color:#e6db74">&#34;Please input: &#34;</span>);
</span></span><span style="display:flex;"><span>                scanf(<span style="color:#e6db74">&#34;%s&#34;</span>, buf);
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">if</span> (strcmp(buf, <span style="color:#e6db74">&#34;quit&#34;</span>) <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>                        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>                }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;Exit...</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>另外 <code>api</code> 中也提供了下面 2 个特殊的 <code>handler</code>:</p>
<ul>
<li>
<p><code>SIG_IGN</code></p>
<p>忽略此信号</p>
</li>
<li>
<p><code>SIG_DFL</code></p>
<p>恢复此信号的默认行为</p>
</li>
</ul>
<h3 id="sigaction-函数"><code>sigaction</code> 函数</h3>
<p><strong>原型：</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">sigaction</span>(<span style="color:#66d9ef">int</span> sig, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">struct</span> sigaction <span style="color:#f92672">*</span><span style="color:#66d9ef">restrict</span> act,
</span></span><span style="display:flex;"><span>           <span style="color:#66d9ef">struct</span> sigaction <span style="color:#f92672">*</span><span style="color:#66d9ef">restrict</span> oact);
</span></span></code></pre></div><p>其中 <code>sig</code> 为 <code>signal number</code>, <code>act</code> 指定信号的处理行为， <code>oact</code> 如果不为 <code>NULL</code> 则返回信号之前的处理行为。</p>
<p><code>struct sigaction</code> 的主要成员如下：</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>名称</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>void(*) (int)</td>
<td>sa_handler</td>
<td>处理函数指针，同 signal 函数中的 <code>func</code> 参数</td>
</tr>
<tr>
<td>sigset_t</td>
<td>sa_mask</td>
<td>信号屏蔽字，是指当前被阻塞的一组信号，不能被当前进程收到</td>
</tr>
<tr>
<td>int</td>
<td>sa_flags</td>
<td>处理行为修改器，指明哪种处理函数生效，详见下文</td>
</tr>
<tr>
<td>void(*) (int, siginfo_t *, void *)</td>
<td>sa_sigaction</td>
<td>处理函数指针，仅 sa_flags == SA_SIGINFO 时有效</td>
</tr>
</tbody>
</table>
<p>其中 <code>sa_flags</code> 主要可以设置为以下值：</p>
<ul>
<li>
<p>SA_NOCLDSTOP</p>
<p>子进程停止时不产生 <code>SIGCHLD</code> 信号</p>
</li>
<li>
<p>SA_RESETHAND</p>
<p>将信号的处理函数在处理函数的入口重置为 <code>SIG_DFL</code></p>
</li>
<li>
<p>SA_RESTART</p>
<p>重启可中断的函数而不是给出 <code>EINTR</code> 错误</p>
</li>
<li>
<p>SA_SIGINFO</p>
<p>使用 <code>sa_sigaction</code> 做为信号的处理函数</p>
</li>
<li>
<p>SA_NODEFER</p>
<p>捕获到信号时不将它添加到信号屏蔽字中</p>
</li>
</ul>
<p>简单的代码示例如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;string.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;signal.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define SIG SIGINT
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">sig_handler</span>(<span style="color:#66d9ef">int</span> sig, siginfo_t <span style="color:#f92672">*</span>si, <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>data)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;Caught signal: %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, sig);
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;Sender pid: %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, si<span style="color:#f92672">-&gt;</span>si_pid);
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;Sender uid: %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, si<span style="color:#f92672">-&gt;</span>si_uid);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">int</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">sig_caught</span>(<span style="color:#66d9ef">int</span> sig)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;Start caught signal: %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, sig);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">struct</span> sigaction sa;
</span></span><span style="display:flex;"><span>        sa.sa_flags <span style="color:#f92672">=</span> SA_SIGINFO;
</span></span><span style="display:flex;"><span>        sa.sa_sigaction <span style="color:#f92672">=</span> sig_handler;
</span></span><span style="display:flex;"><span>        sigemptyset(<span style="color:#f92672">&amp;</span>sa.sa_mask);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> ret <span style="color:#f92672">=</span> sigaction(sig, <span style="color:#f92672">&amp;</span>sa, NULL);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (ret <span style="color:#f92672">==</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>) {
</span></span><span style="display:flex;"><span>                printf(<span style="color:#e6db74">&#34;Failed to caught signal: %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, sig);
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">main</span>(<span style="color:#66d9ef">int</span> argc, <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>argv[])
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (sig_caught(SIG) <span style="color:#f92672">==</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>) {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;Caught signal(%d), input &#39;quit&#39; to exit...</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, SIG);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">char</span> buf[<span style="color:#ae81ff">1024</span>] <span style="color:#f92672">=</span> {<span style="color:#ae81ff">0</span>};
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">while</span>(<span style="color:#ae81ff">1</span>) {
</span></span><span style="display:flex;"><span>                printf(<span style="color:#e6db74">&#34;Please input: &#34;</span>);
</span></span><span style="display:flex;"><span>                scanf(<span style="color:#e6db74">&#34;%s&#34;</span>, buf);
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">if</span> (strcmp(buf, <span style="color:#e6db74">&#34;quit&#34;</span>) <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>                        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>                }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;Exit...</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="信号屏蔽字">信号屏蔽字</h3>
<p>考虑一下这种情况：在 <code>signal()/sigaction()</code> 返回之前进程就已经收到了需要处理的信号，此时进程会以默认行为来处理，这显然不符合我们的期望。 这时就需要用到信号屏蔽字了，在进程启动时就将需要处理的信号加入的屏蔽字中，等 <code>signal()/sigaction()</code> 返回后再解除屏蔽，解除屏蔽后至少会将收到的待处理信号发送一个给进程。</p>
<p>屏蔽字用到一下函数：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">sigemptyset</span>(sigset_t <span style="color:#f92672">*</span>set);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">sigaddset</span>(sigset_t <span style="color:#f92672">*</span>set, <span style="color:#66d9ef">int</span> signo);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">sigprocmask</span>(<span style="color:#66d9ef">int</span> how, <span style="color:#66d9ef">const</span> sigset_t <span style="color:#f92672">*</span><span style="color:#66d9ef">restrict</span> set,
</span></span><span style="display:flex;"><span>           sigset_t <span style="color:#f92672">*</span><span style="color:#66d9ef">restrict</span> oset);
</span></span></code></pre></div><p><code>sigprocmask</code> 中 <code>set</code> 为需要设置的屏蔽字集， <code>oset</code> 为之前的屏蔽字集， <code>how</code> 控制着 <code>set</code> 如何生效，可设置为以下值：</p>
<ul>
<li>
<p>SIG_BLOCK</p>
<p>该进程的屏蔽字集将为当期屏蔽字集与 <code>set</code> 的并集， <code>set</code> 中包含了需要屏蔽的信号集</p>
</li>
<li>
<p>SIG_UNBLOCK</p>
<p>该进程的屏蔽字集将为当期屏蔽字集与 <code>set</code> 的补集的交集， <code>set</code> 中包含了需要解除屏蔽的信号集</p>
</li>
<li>
<p>SIG_SETMASK</p>
<p>该进程的屏蔽字集将设置为 <code>set</code> 的值</p>
</li>
</ul>
<p>简单的设置流程如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">sig_block</span>(<span style="color:#66d9ef">int</span> sig, <span style="color:#66d9ef">int</span> how)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        sigset_t mask;
</span></span><span style="display:flex;"><span>        sigemptyset(<span style="color:#f92672">&amp;</span>mask)
</span></span><span style="display:flex;"><span>        sigaddset(<span style="color:#f92672">&amp;</span>mask, sig);
</span></span><span style="display:flex;"><span>        sigprocmask(how, <span style="color:#f92672">&amp;</span>mask, NULL);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="信号发送">信号发送</h2>
<p>信号可以通过 <code>kill</code> 函数发送给指定进程，也可以通过 <code>raise</code> 或者 <code>alarm</code> 函数发送给当前执行的线程或进程，下面来分别说说这几个函数。</p>
<h3 id="kill">kill</h3>
<p><strong>原型：</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">kill</span>(pid_t pid, <span style="color:#66d9ef">int</span> sig);
</span></span></code></pre></div><p><code>kill</code> 函数向指定进程发送指定的信号，如果信号为 0 将执行错误检查，信号并不会发送，可以用来检查 <code>pid</code> 的有效性。</p>
<p><code>pid</code> 大于 0 时信号将发送给此进程， <code>pid</code> 小于等于 0 时，如下：</p>
<ul>
<li>
<p>等于 0</p>
<p>信号将发送给发送者所在组里的所有进程</p>
</li>
<li>
<p>等于 -1</p>
<p>信号将发送给所有进程</p>
</li>
<li>
<p>小于 -1</p>
<p>信号将发送给进程组为 <code>pid</code> 绝对值的所有组内进程</p>
</li>
</ul>
<h3 id="alarm">alarm</h3>
<p><strong>原型：</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">unsigned</span> <span style="color:#a6e22e">alarm</span>(<span style="color:#66d9ef">unsigned</span> seconds);
</span></span></code></pre></div><p><code>alarm</code> 函数将在指定的 <code>seconds</code> 之后发送一个 <code>SIGALRM</code> 信号，如果 <code>seconds</code> 为 0, 则取消之前的定时器请求。如果不为 0 则取消之前的请求，重新设置为 <code>seconds</code> 。 如果在等待结束之前有其他的事件产生，那定时器请求也将被取消。</p>
<p>简单的代码示例如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;unistd.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;signal.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">handler</span>(<span style="color:#66d9ef">int</span> sig)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;alarm arrived: %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, sig);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">main</span>(<span style="color:#66d9ef">int</span> argc, <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>argv[])
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        signal(SIGALRM, handler);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        alarm(<span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        sleep(<span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;alarm 5s over</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        alarm(<span style="color:#ae81ff">10</span>);
</span></span><span style="display:flex;"><span>        sleep(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">int</span> remaining <span style="color:#f92672">=</span> alarm(<span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;alarm 10s remain: %u, reset to 3</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, remaining);
</span></span><span style="display:flex;"><span>        sleep(<span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;alarm 3s over</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        alarm(<span style="color:#ae81ff">20</span>);
</span></span><span style="display:flex;"><span>        sleep(<span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        remaining <span style="color:#f92672">=</span> alarm(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;cancel alarm 20s, remian: %u, exit...</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, remaining);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="raise">raise</h3>
<p><strong>原型：</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">raise</span>(<span style="color:#66d9ef">int</span> sig);
</span></span></code></pre></div><p><code>raise</code> 函数将给当前执行的线程或进程发送信号，如果信号处理函数已经被调用， <code>raise</code> 函数将等待信号处理函数调用结束才返回。</p>
<h2 id="结语">结语</h2>
<p>信号处理函数是会被重复调用的，所以必要保存其是可重入的，注意处理逻辑。</p>
<p>另外本文中的代码都在 <a href="https://github.com/jouyouyun/examples/tree/master/signal">signal</a> 中，这个 <code>repo</code> 也有其它的示例，有兴趣的可以看看。</p>
<h2 id="附录">附录</h2>
<h3 id="信号表">信号表</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/* ISO C99 signals.  */</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGINT		2	</span><span style="color:#75715e">/* Interactive attention signal.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGILL		4	</span><span style="color:#75715e">/* Illegal instruction.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGABRT		6	</span><span style="color:#75715e">/* Abnormal termination.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGFPE		8	</span><span style="color:#75715e">/* Erroneous arithmetic operation.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGSEGV		11	</span><span style="color:#75715e">/* Invalid access to storage.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGTERM		15	</span><span style="color:#75715e">/* Termination request.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* Historical signals specified by POSIX. */</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGHUP		1	</span><span style="color:#75715e">/* Hangup.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGQUIT		3	</span><span style="color:#75715e">/* Quit.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGTRAP		5	</span><span style="color:#75715e">/* Trace/breakpoint trap.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGKILL		9	</span><span style="color:#75715e">/* Killed.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define SIGBUS		10	</span><span style="color:#75715e">/* Bus error.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGSYS		12	</span><span style="color:#75715e">/* Bad system call.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGPIPE		13	</span><span style="color:#75715e">/* Broken pipe.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGALRM		14	</span><span style="color:#75715e">/* Alarm clock.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* New(er) POSIX signals (1003.1-2008, 1003.1-2013).  */</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGURG		16	</span><span style="color:#75715e">/* Urgent data is available at a socket.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGSTOP		17	</span><span style="color:#75715e">/* Stop, unblockable.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGTSTP		18	</span><span style="color:#75715e">/* Keyboard stop.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGCONT		19	</span><span style="color:#75715e">/* Continue.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGCHLD		20	</span><span style="color:#75715e">/* Child terminated or stopped.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGTTIN		21	</span><span style="color:#75715e">/* Background read from control terminal.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGTTOU		22	</span><span style="color:#75715e">/* Background write to control terminal.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGPOLL		23	</span><span style="color:#75715e">/* Pollable event occurred (System V).  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGXCPU		24	</span><span style="color:#75715e">/* CPU time limit exceeded.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGXFSZ		25	</span><span style="color:#75715e">/* File size limit exceeded.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGVTALRM	26	</span><span style="color:#75715e">/* Virtual timer expired.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGPROF		27	</span><span style="color:#75715e">/* Profiling timer expired.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGUSR1		30	</span><span style="color:#75715e">/* User-defined signal 1.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGUSR2		31	</span><span style="color:#75715e">/* User-defined signal 2.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* Nonstandard signals found in all modern POSIX systems
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">   (including both BSD and Linux).  */</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGWINCH	28	</span><span style="color:#75715e">/* Window size change (4.3 BSD, Sun).  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* Archaic names for compatibility.  */</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGIO		SIGPOLL	</span><span style="color:#75715e">/* I/O now possible (4.2 BSD).  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGIOT		SIGABRT	</span><span style="color:#75715e">/* IOT instruction, abort() on a PDP-11.  */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define	SIGCLD		SIGCHLD	</span><span style="color:#75715e">/* Old System V name */</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* Not all systems support real-time signals.  bits/signum.h indicates
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">   that they are supported by overriding __SIGRTMAX to a value greater
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">   than __SIGRTMIN.  These constants give the kernel-level hard limits,
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">   but some real-time signals may be used internally by glibc.  Do not
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">   use these constants in application code; use SIGRTMIN and SIGRTMAX
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">   (defined in signal.h) instead.  */</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define __SIGRTMIN	32
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define __SIGRTMAX	__SIGRTMIN
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* Biggest signal number + 1 (including real-time signals).  */</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define _NSIG		(__SIGRTMAX + 1)
</span></span></span></code></pre></div><p>使用 <code>kill -l</code> 命令也可查看信号列表.</p>
<h4 id="可产生-coredump-的信号">可产生 <code>coredump</code> 的信号</h4>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>3</td>
<td>SIGQUIT</td>
<td>终止进程</td>
</tr>
<tr>
<td>4</td>
<td>SIGILL</td>
<td>非法指令</td>
</tr>
<tr>
<td>5</td>
<td>SIGTRAP</td>
<td>自陷</td>
</tr>
<tr>
<td>6</td>
<td>SIGABRT</td>
<td>异常终止</td>
</tr>
<tr>
<td>7</td>
<td>SIGBUS</td>
<td>总线错误</td>
</tr>
<tr>
<td>8</td>
<td>SIGFPE</td>
<td>浮点数异常</td>
</tr>
<tr>
<td>11</td>
<td>SIGSEGV</td>
<td>段错误</td>
</tr>
<tr>
<td>6</td>
<td>SIGIOT</td>
<td>I/O 自陷</td>
</tr>
</tbody>
</table>
<p><code>SIGIOT</code> 在 <code>PDP-11</code> 上产生 <code>LOT</code> 指令, 同 <code>SIGABRT</code> .</p><ul class="pa0">
  
   <li class="list di">
     <a href="/tags/signal" class="link f5 grow no-underline br-pill ba ph3 pv2 mb2 dib black sans-serif">signal</a>
   </li>
  
   <li class="list di">
     <a href="/tags/sigaction" class="link f5 grow no-underline br-pill ba ph3 pv2 mb2 dib black sans-serif">sigaction</a>
   </li>
  
   <li class="list di">
     <a href="/tags/alarm" class="link f5 grow no-underline br-pill ba ph3 pv2 mb2 dib black sans-serif">alarm</a>
   </li>
  
   <li class="list di">
     <a href="/tags/kill" class="link f5 grow no-underline br-pill ba ph3 pv2 mb2 dib black sans-serif">kill</a>
   </li>
  
   <li class="list di">
     <a href="/tags/raise" class="link f5 grow no-underline br-pill ba ph3 pv2 mb2 dib black sans-serif">raise</a>
   </li>
  
</ul>
<div class="mt6 instapaper_ignoref">
      
      
      </div>
    </div>

    <aside class="w-30-l mt6-l">




</aside>

  </article>

    </main>
    <footer class="bg-black bottom-0 w-100 pa3" role="contentinfo">
  <div class="flex justify-between">
  <a class="f4 fw4 hover-white no-underline white-70 dn dib-ns pv2 ph3" href="https://jouyouyun.github.io" >
    &copy;  jouyouyun 2023 
  </a>
    <div>
<div class="ananke-socials">
  
    <a href="https://github.com/jouyouyun" target="_blank" class="github ananke-social-link link-transition stackoverflow link dib z-999 pt3 pt0-l mr1" title="GitHub link" rel="noopener" aria-label="follow on GitHub——Opens in a new window">
      
        <span class="icon"><svg style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512"  xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
  <path d="M256,32C132.3,32,32,134.8,32,261.7c0,101.5,64.2,187.5,153.2,217.9c11.2,2.1,15.3-5,15.3-11.1   c0-5.5-0.2-19.9-0.3-39.1c-62.3,13.9-75.5-30.8-75.5-30.8c-10.2-26.5-24.9-33.6-24.9-33.6c-20.3-14.3,1.5-14,1.5-14   c22.5,1.6,34.3,23.7,34.3,23.7c20,35.1,52.4,25,65.2,19.1c2-14.8,7.8-25,14.2-30.7c-49.7-5.8-102-25.5-102-113.5   c0-25.1,8.7-45.6,23-61.6c-2.3-5.8-10-29.2,2.2-60.8c0,0,18.8-6.2,61.6,23.5c17.9-5.1,37-7.6,56.1-7.7c19,0.1,38.2,2.6,56.1,7.7   c42.8-29.7,61.5-23.5,61.5-23.5c12.2,31.6,4.5,55,2.2,60.8c14.3,16.1,23,36.6,23,61.6c0,88.2-52.4,107.6-102.3,113.3   c8,7.1,15.2,21.1,15.2,42.5c0,30.7-0.3,55.5-0.3,63c0,6.1,4,13.3,15.4,11C415.9,449.1,480,363.1,480,261.7   C480,134.8,379.7,32,256,32z"/>
</svg>
</span>
      
<span class="new-window"><svg  height="8px"  style="enable-background:new 0 0 1000 1000;" version="1.1" viewBox="0 0 1000 1000"  xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<path d="M598 128h298v298h-86v-152l-418 418-60-60 418-418h-152v-86zM810 810v-298h86v298c0 46-40 86-86 86h-596c-48 0-86-40-86-86v-596c0-46 38-86 86-86h298v86h-298v596h596z" style="fill-rule:evenodd;clip-rule:evenodd;"/>
</svg>
</span></a>
  
</div>
</div>
  </div>
</footer>

  </body>
</html>
